package com.quanyan.place.biz.impl;

import com.quanyan.api.APIResponse;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.http.HttpClientUtils;
import com.quanyan.common.utils.GsonUtils;
import com.quanyan.common.utils.RandomStringGenerator;
import com.quanyan.place.biz.SmsService;
import com.quanyan.place.cache.PlaceRedisTemplate;
import com.quanyan.place.entity.TbSmsContent;
import com.quanyan.place.mapper.TbSmsContentMapper;
import com.quanyan.redisCluster.utils.RedisConstants;
import com.quanyan.redisCluster.utils.RedisKey;
import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import sms.SmsApi;
import sms.impl.ChuangLanSms;
import sms.impl.HuyiSms;
import sms.model.Result;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by yangyun on 2016/6/8.
 */
@Service
public class PlaceSmsServiceImpl implements SmsService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private String REDIS_USER_PHONE_CODE_SET = "user_phone_code_set_";
    private String REDIS_USER_PHONE_MESSAGE_RESEND = "user_phone_message_resend";


    @Value("${c.sendSmsApi}")
    private String sendSmsApi;

    @Value("${c.checkCodeApi}")
    private String checkCodeApi;

    @Value("${c.address}")
    private String address;

    @Autowired
    private TbSmsContentMapper tbSmsContentMapper;

    @Autowired
    private PlaceRedisTemplate placeCache;

    @Override
    public Result sendMessageToPhone(String phone, Byte templateId, String[] args, boolean failResend) {

        TbSmsContent tbSmsContent = new TbSmsContent();
        tbSmsContent.setPhone(phone);

        JSONObject object = new JSONObject();
        object.element("templateId", templateId);
        object.element("args", JSONArray.fromObject(args));
        tbSmsContent.setContent(object.toString());
        tbSmsContent.setState(Constants.NO);
        this.tbSmsContentMapper.insertSelective(tbSmsContent);

        SmsApi smsApi = new HuyiSms();
        Result result = smsApi.sendMsg(phone, templateId, args);
        if (!result.isStatus()) {
            smsApi = new ChuangLanSms();
            result = smsApi.sendMsg(phone, templateId, args);
        }

        if (result != null && result.isStatus()) {
            tbSmsContent.setId(tbSmsContent.getId());
            tbSmsContent.setState(Constants.YES);
            this.tbSmsContentMapper.updateByPrimaryKeySelective(tbSmsContent);
        }
        return result;
    }

    /**
     *  发送验证码
     * @param phone  目标手机
     * @param templateId 模板id
     * @param resend 重发时间
     * @param exp  过期时间
     * @return
     */
    public Result sendValidCodetToPhone(String phone, Byte templateId, int resend, int exp) {
        //判断验证码是否过期.
        String code = (String)placeCache.get(RedisConstants.PLACE_FAMILY_KEY + REDIS_USER_PHONE_MESSAGE_RESEND + templateId + phone);
        if (code == null) {
            code = RandomStringGenerator.getRandomDigitByLength(4);
            //您的验证码是：【变量】，【变量】分钟内有效，短信编号【变量】。
            Result result = sendMessageToPhone(phone, templateId, new String[]{code, (exp / 60) + ""}, false); // TODO
            if (result.isStatus()) {
                placeCache.zadd(RedisConstants.PLACE_FAMILY_KEY + REDIS_USER_PHONE_CODE_SET + templateId + phone, System.currentTimeMillis() + (exp * 1000), code);
                placeCache.save(RedisConstants.PLACE_FAMILY_KEY + REDIS_USER_PHONE_MESSAGE_RESEND + templateId + phone, code, resend);
            }
            return result;
        } else {
            return Result.returnFail(Result.SMS_SEND_TOO_OFTEN);
        }
    }

    /**
     * 校验验证码
     * @param phone
     * @param templateId
     * @param code
     * @return
     */
    public boolean verifyValidCode(String phone, Byte templateId, String code) {
        RedisKey redisKey = new RedisKey(RedisConstants.PLACE_FAMILY_KEY, REDIS_USER_PHONE_CODE_SET + templateId + phone);
        double score = placeCache.zScore(redisKey.getRedisKey(), code);
        if (score == 0.0) {
            logger.warn("verifyValidCode failed, code is not found, phone:" + phone + ",code:" + code);
            return false;
        }
        if ((long) score >= System.currentTimeMillis()) {
            placeCache.delteKey(redisKey);
            placeCache.delteKey(new RedisKey(RedisConstants.PLACE_FAMILY_KEY,REDIS_USER_PHONE_MESSAGE_RESEND + templateId + phone));
            return true;
        }
        logger.warn("verifyValidCode failed, code expired,phone:" + phone + ",code:" + code + ",score:" + score);
        return false;
    }


    /**
     * 短信下发
     * @param mobiles
     * @param templateId
     * @param type
     * @param params
     * @return
     */
    @Override
    @Async
    public APIResponse sendSms(List<String> mobiles, int templateId, int type, List<String> params) {
        Map headMap = new HashMap<>();
        headMap.put("userCookiesName","");
        Map paramMap = new HashMap();
        paramMap.put("ver","");
        paramMap.put("protocol_ver",1);
        paramMap.put("mobiles",mobiles);
        paramMap.put("template_id",templateId);
        paramMap.put("type",type);
        paramMap.put("params",params);
        APIResponse response = null;
        String result = null;
        try {
            result = HttpClientUtils.postJson(address + sendSmsApi, GsonUtils.toJson(paramMap), headMap);
            response = GsonUtils.jsonStrToEntity(result, APIResponse.class);
            logger.info("========================短信返回结果===============================");
            logger.info("mobiles==========================="+ com.alibaba.fastjson.JSON.toJSONString(mobiles));
            logger.info("response.getErrcode()============="+response.getErrcode());
            logger.info("response.isRet()=================="+response.isRet());
            logger.info("response.getErrmsg()=============="+response.getErrmsg());
        } catch (Exception e) {
            logger.info("请求返回信息：{}，异常信息：{}", result,e);
        }
        return response;
    }

    /**
     * 验证码校验
     * @param validCode 验证码
     * @return
     */
    @Override
    public APIResponse checkCode(String validCode,String mobile) {
        Map headMap = new HashMap<>();
        headMap.put("userCookiesName","");
        Map paramMap = new HashMap();
        paramMap.put("ver","");
        paramMap.put("protocol_ver",1);
        paramMap.put("verifycode",validCode);
        paramMap.put("mobile",mobile);
        APIResponse response = null;
        String result = null;
        try {
            result = HttpClientUtils.postJson(address + checkCodeApi, GsonUtils.toJson(paramMap), headMap);
            response = GsonUtils.jsonStrToEntity(result, APIResponse.class);
        } catch (Exception e) {
            logger.info("请求返回信息：{}，异常信息：{}", result,e);
        }
        return response;
    }
}
